home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / Emacs / buffer.c < prev    next >
C/C++ Source or Header  |  1989-05-30  |  13KB  |  366 lines

  1. /* buffer.c */
  2.  
  3. /*
  4.  * Buffer management.
  5.  * Some of the functions are internal,
  6.  * and some are actually attached to user
  7.  * keys. Like everyone else, they set hints
  8.  * for the display system.
  9.  */
  10. #include        <stdio.h>
  11. #include        "ed.h"
  12.  
  13. /*
  14.  * Attach a buffer to a window. The
  15.  * values of dot and mark come from the buffer
  16.  * if the use count is 0. Otherwise, they come
  17.  * from some other window.
  18.  */
  19. usebuffer(f, n)
  20. {
  21.         register BUFFER *bp;
  22.         register WINDOW *wp;
  23.         register int    s;
  24.         char            bufn[NBUFN];
  25.  
  26.         if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
  27.                 return (s);
  28.         if ((bp=bfind(bufn, TRUE, 0)) == NULL)
  29.                 return (FALSE);
  30.         if (--curbp->b_nwnd == 0) {             /* Last use.            */
  31.                 curbp->b_dotp  = curwp->w_dotp;
  32.                 curbp->b_doto  = curwp->w_doto;
  33.                 curbp->b_markp = curwp->w_markp;
  34.                 curbp->b_marko = curwp->w_marko;
  35.         }
  36.         curbp = bp;                             /* Switch.              */
  37.         curwp->w_bufp  = bp;
  38.         curwp->w_linep = bp->b_linep;           /* For macros, ignored. */
  39.         curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty.         */
  40.         if (bp->b_nwnd++ == 0) {                /* First use.           */
  41.                 curwp->w_dotp  = bp->b_dotp;
  42.                 curwp->w_doto  = bp->b_doto;
  43.                 curwp->w_markp = bp->b_markp;
  44.                 curwp->w_marko = bp->b_marko;
  45.                 return (TRUE);
  46.         }
  47.         wp = wheadp;                            /* Look for old.        */
  48.         while (wp != NULL) {
  49.                 if (wp!=curwp && wp->w_bufp==bp) {
  50.                         curwp->w_dotp  = wp->w_dotp;
  51.                         curwp->w_doto  = wp->w_doto;
  52.                         curwp->w_markp = wp->w_markp;
  53.                         curwp->w_marko = wp->w_marko;
  54.                         break;
  55.                 }
  56.                 wp = wp->w_wndp;
  57.         }
  58.         return (TRUE);
  59. }
  60.  
  61. /*
  62.  * Dispose of a buffer, by name.
  63.  * Ask for the name. Look it up (don't get too
  64.  * upset if it isn't there at all!). Get quite upset
  65.  * if the buffer is being displayed. Clear the buffer (ask
  66.  * if the buffer has been changed). Then free the header
  67.  * line and the buffer header. Bound to "C-X K".
  68.  */
  69. killbuffer(f, n)
  70. {
  71.         register BUFFER *bp;
  72.         register BUFFER *bp1;
  73.         register BUFFER *bp2;
  74.         register int    s;
  75.         char            bufn[NBUFN];
  76.  
  77.         if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
  78.                 return (s);
  79.         if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown.     */
  80.                 return (TRUE);
  81.         if (bp->b_nwnd != 0) {                  /* Error if on screen.  */
  82.                 mlwrite("Buffer is being displayed");
  83.                 return (FALSE);
  84.         }
  85.         if ((s=bclear(bp)) != TRUE)             /* Blow text away.      */
  86.                 return (s);
  87.         free((char *) bp->b_linep);             /* Release header line. */
  88.         bp1 = NULL;                             /* Find the header.     */
  89.         bp2 = bheadp;
  90.         while (bp2 != bp) {
  91.                 bp1 = bp2;
  92.                 bp2 = bp2->b_bufp;
  93.         }
  94.         bp2 = bp2->b_bufp;                      /* Next one in chain.   */
  95.         if (bp1 == NULL)                        /* Unlink it.           */
  96.                 bheadp = bp2;
  97.         else
  98.                 bp1->b_bufp = bp2;
  99.         free((char *) bp);                      /* Release buffer block */
  100.         return (TRUE);
  101. }
  102.  
  103. /*
  104.  * List all of the active
  105.  * buffers. First update the special
  106.  * buffer that holds the list. Next make
  107.  * sure at least 1 window is displaying the
  108.  * buffer list, splitting the screen if this
  109.  * is what it takes. Lastly, repaint all of
  110.  * the windows that are displaying the
  111.  * list. Bound to "C-X C-B".
  112.  */
  113. listbuffers(f, n)
  114. {
  115.         register WINDOW *wp;
  116.         register BUFFER *bp;
  117.         register int    s;
  118.  
  119.         if ((s=makelist()) != TRUE)
  120.                 return (s);
  121.         if (blistp->b_nwnd == 0) {              /* Not on screen yet.   */
  122.                 if ((wp=wpopup()) == NULL)
  123.                         return (FALSE);
  124.                 bp = wp->w_bufp;
  125.                 if (--bp->b_nwnd == 0) {
  126.                         bp->b_dotp  = wp->w_dotp;
  127.                         bp->b_doto  = wp->w_doto;
  128.                         bp->b_markp = wp->w_markp;
  129.                         bp->b_marko = wp->w_marko;
  130.                 }
  131.                 wp->w_bufp  = blistp;
  132.                 ++blistp->b_nwnd;
  133.         }
  134.         wp = wheadp;
  135.         while (wp != NULL) {
  136.                 if (wp->w_bufp == blistp) {
  137.                         wp->w_linep = lforw(blistp->b_linep);
  138.                         wp->w_dotp  = lforw(blistp->b_linep);
  139.                         wp->w_doto  = 0;
  140.                         wp->w_markp = NULL;
  141.                         wp->w_marko = 0;
  142.                         wp->w_flag |= WFMODE|WFHARD;
  143.                 }
  144.                 wp = wp->w_wndp;
  145.         }
  146.         return (TRUE);
  147. }
  148.  
  149. /*
  150.  * This routine rebuilds the
  151.  * text in the special secret buffer
  152.  * that holds the buffer list. It is called
  153.  * by the list buffers command. Return TRUE
  154.  * if everything works. Return FALSE if there
  155.  * is an error (if there is no memory).
  156.  */
  157. makelist()
  158. {
  159.         register char   *cp1;
  160.         register char   *cp2;
  161.         register int    c;
  162.         register BUFFER *bp;
  163.         register LINE   *lp;
  164.         register int    nbytes;
  165.         register int    s;
  166.         register int    type;
  167.         char            b[6+1];
  168.         char            line[128];
  169.  
  170.         blistp->b_flag &= ~BFCHG;               /* Don't complain!      */
  171.         if ((s=bclear(blistp)) != TRUE)         /* Blow old text away   */
  172.                 return (s);
  173.         strcpy(blistp->b_fname, "");
  174.         if (addline("C   Size Buffer           File") == FALSE
  175.         ||  addline("-   ---- ------           ----") == FALSE)
  176.                 return (FALSE);
  177.         bp = bheadp;                            /* For all buffers      */
  178.         while (bp != NULL) {
  179.                 if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones.     */
  180.                         bp = bp->b_bufp;
  181.                         continue;
  182.                 }
  183.                 cp1 = &line[0];                 /* Start at left edge   */
  184.                 if ((bp->b_flag&BFCHG) != 0)    /* "*" if changed       */
  185.                         *cp1++ = '*';
  186.                 else
  187.                         *cp1++ = ' ';
  188.                 *cp1++ = ' ';                   /* Gap.                 */
  189.                 nbytes = 0;                     /* Count bytes in buf.  */
  190.                 lp = lforw(bp->b_linep);
  191.                 while (lp != bp->b_linep) {
  192.                         nbytes += llength(lp)+1;
  193.                         lp = lforw(lp);
  194.                 }
  195.                 itoa(b, 6, nbytes);             /* 6 digit buffer size. */
  196.                 cp2 = &b[0];
  197.                 while ((c = *cp2++) != 0)
  198.                         *cp1++ = c;
  199.                 *cp1++ = ' ';                   /* Gap.                 */
  200.                 cp2 = &bp->b_bname[0];          /* Buffer name          */
  201.                 while ((c = *cp2++) != 0)
  202.                         *cp1++ = c;
  203.                 cp2 = &bp->b_fname[0];          /* File name            */
  204.                 if (*cp2 != 0) {
  205.                         while (cp1 < &line[1+1+6+1+NBUFN+1])
  206.                                 *cp1++ = ' ';           
  207.                         while ((c = *cp2++) != 0) {
  208.                                 if (cp1 < &line[128-1])
  209.                                         *cp1++ = c;
  210.                         }
  211.                 }
  212.                 *cp1 = 0;                       /* Add to the buffer.   */
  213.                 if (addline(line) == FALSE)
  214.                         return (FALSE);
  215.                 bp = bp->b_bufp;
  216.         }
  217.         return (TRUE);                          /* All done             */
  218. }
  219.  
  220. itoa(buf, width, num)
  221. register char   buf[];
  222. register int    width;
  223. register int    num;
  224. {
  225.         buf[width] = 0;                         /* End of string.       */
  226.         while (num >= 10) {                     /* Conditional digits.  */
  227.                 buf[--width] = (num%10) + '0';
  228.                 num /= 10;
  229.         }
  230.         buf[--width] = num + '0';               /* Always 1 digit.      */
  231.         while (width != 0)                      /* Pad with blanks.     */
  232.                 buf[--width] = ' ';
  233. }
  234.  
  235. /*
  236.  * The argument "text" points to
  237.  * a string. Append this line to the
  238.  * buffer list buffer. Handcraft the EOL
  239.  * on the end. Return TRUE if it worked and
  240.  * FALSE if you ran out of room.
  241.  */
  242. addline(text)
  243. char    *text;
  244. {
  245.         register LINE   *lp;
  246.         register int    i;
  247.         register int    ntext;
  248.  
  249.         ntext = strlen(text);
  250.         if ((lp=lalloc(ntext)) == NULL)
  251.                 return (FALSE);
  252.         for (i=0; i<ntext; ++i)
  253.                 lputc(lp, i, text[i]);
  254.         blistp->b_linep->l_bp->l_fp = lp;       /* Hook onto the end    */
  255.         lp->l_bp = blistp->b_linep->l_bp;
  256.         blistp->b_linep->l_bp = lp;
  257.         lp->l_fp = blistp->b_linep;
  258.         if (blistp->b_dotp == blistp->b_linep)  /* If "." is at the end */
  259.                 blistp->b_dotp = lp;            /* move it to new line  */
  260.         return (TRUE);
  261. }
  262.  
  263. /*
  264.  * Look through the list of
  265.  * buffers. Return TRUE if there
  266.  * are any changed buffers. Buffers
  267.  * that hold magic internal stuff are
  268.  * not considered; who cares if the
  269.  * list of buffer names is hacked.
  270.  * Return FALSE if no buffers
  271.  * have been changed.
  272.  */
  273. anycb()
  274. {
  275.         register BUFFER *bp;
  276.  
  277.         bp = bheadp;
  278.         while (bp != NULL) {
  279.                 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
  280.                         return (TRUE);
  281.                 bp = bp->b_bufp;
  282.         }
  283.         return (FALSE);
  284. }
  285.  
  286. /*
  287.  * Find a buffer, by name. Return a pointer
  288.  * to the BUFFER structure associated with it. If
  289.  * the named buffer is found, but is a TEMP buffer (like
  290.  * the buffer list) conplain. If the buffer is not found
  291.  * and the "cflag" is TRUE, create it. The "bflag" is
  292.  * the settings for the flags in in buffer.
  293.  */
  294. BUFFER  *
  295. bfind(bname, cflag, bflag)
  296. register char   *bname;
  297. {
  298.         register BUFFER *bp;
  299.         register LINE   *lp;
  300.  
  301.         bp = bheadp;
  302.         while (bp != NULL) {
  303.                 if (strcmp(bname, bp->b_bname) == 0) {
  304.                         if ((bp->b_flag&BFTEMP) != 0) {
  305.                                 mlwrite("Cannot select builtin buffer");
  306.                                 return (NULL);
  307.                         }
  308.                         return (bp);
  309.                 }
  310.                 bp = bp->b_bufp;
  311.         }
  312.         if (cflag != FALSE) {
  313.                 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
  314.                         return (NULL);
  315.                 if ((lp=lalloc(0)) == NULL) {
  316.                         free((char *) bp);
  317.                         return (NULL);
  318.                 }
  319.                 bp->b_bufp  = bheadp;
  320.                 bheadp = bp;
  321.                 bp->b_dotp  = lp;
  322.                 bp->b_doto  = 0;
  323.                 bp->b_markp = NULL;
  324.                 bp->b_marko = 0;
  325.                 bp->b_flag  = bflag;
  326.                 bp->b_nwnd  = 0;
  327.                 bp->b_linep = lp;
  328.                 strcpy(bp->b_fname, "");
  329.                 strcpy(bp->b_bname, bname);
  330.                 lp->l_fp = lp;
  331.                 lp->l_bp = lp;
  332.         }
  333.         return (bp);
  334. }
  335.  
  336. /*
  337.  * This routine blows away all of the text
  338.  * in a buffer. If the buffer is marked as changed
  339.  * then we ask if it is ok to blow it away; this is
  340.  * to save the user the grief of losing text. The
  341.  * window chain is nearly always wrong if this gets
  342.  * called; the caller must arrange for the updates
  343.  * that are required. Return TRUE if everything
  344.  * looks good.
  345.  */
  346. bclear(bp)
  347. register BUFFER *bp;
  348. {
  349.         register LINE   *lp;
  350.         register int    s;
  351.         
  352.         if ((bp->b_flag&BFTEMP) == 0            /* Not scratch buffer.  */
  353.         && (bp->b_flag&BFCHG) != 0              /* Something changed    */
  354.         && (s=mlyesno("Discard changes")) != TRUE)
  355.                 return (s);
  356.         bp->b_flag  &= ~BFCHG;                  /* Not changed          */
  357.         while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  358.                 lfree(lp);
  359.         bp->b_dotp  = bp->b_linep;              /* Fix "."              */
  360.         bp->b_doto  = 0;
  361.         bp->b_markp = NULL;                     /* Invalidate "mark"    */
  362.         bp->b_marko = 0;
  363.         return (TRUE);
  364. }
  365.  
  366.